package com.example.workflow.controller;

import com.example.workflow.common.Result;
import com.example.workflow.dto.flow.FlowTaskDto;
import com.example.workflow.enums.FlowComment;
import com.example.workflow.vo.flow.ProcessDetail;
import com.example.workflow.vo.flow.TaskVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import liquibase.repackaged.org.apache.commons.collections4.CollectionUtils;
import lombok.Setter;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

@Tag ( name = "采购相关管理", description = "采购相关管理")
@RestController
@RequestMapping ("/procurement")
@Setter(onMethod_ = @Resource )
public class ProcurementController {

	private RepositoryService repositoryService;

	private RuntimeService runtimeService;

	private IdentityService identityService;

	private TaskService taskService;

	private HistoryService historyService;


	@PostMapping ( "/startProcess" )
	@Operation ( summary = "启动流程", description = "启动流程" )
	public Result < String > startProcess ( @RequestBody TaskVo dto ) {
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery ()
				.processDefinitionId ( dto.getProcessId () ).latestVersion ().singleResult ();
		if ( Objects.nonNull ( processDefinition ) && processDefinition.isSuspended () ) {
			return Result.error ( "流程已被挂起,请先激活流程" );
		}
		// 设置流程发起人id到流程中
		Map < String,Object > variables = new HashMap <> ();
		identityService.setAuthenticatedUserId ( dto.getUserId () );
		// 流程发起时 跳过发起人节点
		ProcessInstance processInstance = runtimeService.startProcessInstanceById ( dto.getProcessId () , variables );
		// 给第一步申请人节点设置任务执行人和意见
		Task task = taskService.createTaskQuery ().processInstanceId ( processInstance.getProcessInstanceId () )
				.singleResult ();
		if ( Objects.nonNull ( task ) ) {
			taskService.addComment ( task.getId () , processInstance.getProcessInstanceId () , FlowComment.NORMAL.getType () ,
					dto.getRemark () );
			taskService.setAssignee ( task.getId () ,  dto.getUserId () );
			taskService.complete ( task.getId () , variables );
		}
		return Result.success ( processInstance.getId ()  );
	}

	@Operation ( summary = "我发起的流程", description = "我发起的流程" )
	@PostMapping ( value = "/myProcessList" )
	public Result < List < FlowTaskDto > > myProcessList ( @RequestBody TaskVo dto ) {
		List < FlowTaskDto > voList = new ArrayList <> ();
		// 获取指定定义流程下自己发起的流程实例(进行中)
		List < HistoricProcessInstance > historicProcessInstances = historyService.createHistoricProcessInstanceQuery()
				.startedBy(dto.getUserId ())
				.processDefinitionId ( dto.getProcessId () )
				.orderByProcessInstanceStartTime()
				.desc().list ();

		for ( HistoricProcessInstance hisIns : historicProcessInstances ) {
			FlowTaskDto flowTask = new FlowTaskDto();
			flowTask.setCreateTime(hisIns.getStartTime());
			flowTask.setFinishTime(hisIns.getEndTime());
			flowTask.setProcInsId(hisIns.getId());
			// 计算耗时
			if (Objects.nonNull(hisIns.getEndTime())) {
				long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime();
				flowTask.setDuration(getDate(time));
			} else {
				long time = System.currentTimeMillis() - hisIns.getStartTime().getTime();
				flowTask.setDuration(getDate(time));
			}
			// 流程定义信息
			ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
					.processDefinitionId(hisIns.getProcessDefinitionId()).singleResult();
			flowTask.setDeployId(pd.getDeploymentId());
			flowTask.setProcDefName(pd.getName());
			flowTask.setProcDefVersion(pd.getVersion());
			flowTask.setCategory(pd.getCategory());
			flowTask.setProcDefVersion(pd.getVersion());
			// 当前所处流程
			List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list();
			if ( CollectionUtils.isNotEmpty(taskList)) {
				Task task = taskList.get (0);
				flowTask.setTaskId(task.getId());
				flowTask.setTaskName(task.getName());
				//				if ( StringUtils.isNotBlank(task.getAssignee())) {
				//					// 当前任务节点办理人信息
				////					SysUser sysUser = sysUserService.selectUserById(Long.parseLong(taskList.get(0).getAssignee()));
				////					flowTask.setAssigneeId(sysUser.getUserId());
				////					flowTask.setAssigneeName(sysUser.getNickName());
				////					flowTask.setAssigneeDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
				//				}
			} else {
				HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
						.processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list().get(0);

				flowTask.setTaskId(historicTaskInstance.getId());
				flowTask.setTaskName(historicTaskInstance.getName());
				//				if (StringUtils.isNotBlank(historicTaskInstance.getAssignee())) {
				//					// 当前任务节点办理人信息
				////					SysUser sysUser = sysUserService.selectUserById(Long.parseLong(historicTaskInstance.get(0).getAssignee()));
				////					flowTask.setAssigneeId(sysUser.getUserId());
				////					flowTask.setAssigneeName(sysUser.getNickName());
				////					flowTask.setAssigneeDeptName(Objects.nonNull(sysUser.getDept()) ? sysUser.getDept().getDeptName() : "");
				//				}
			}
			voList.add(flowTask);
		}
		return Result.success ( voList );
	}

	@PostMapping ( "myTodoList" )
	@Operation ( summary = "我的待办任务", description = "我的待办任务" )
	public Result < List < FlowTaskDto > >  myTodoList ( @RequestBody TaskVo dto ) {
		// 只查看自己的数据
		List < Task > tasks = taskService.createTaskQuery ().active ()
				.includeProcessVariables ()
				.processDefinitionId( dto.getProcessId () )
				.taskCandidateGroupIn ( dto.getRoleList () )
				.list ();
		List < FlowTaskDto > taskDtoList = new ArrayList <> ();
		for ( Task task : tasks ) {
			FlowTaskDto flowTask = new FlowTaskDto ();
			// 当前流程信息
			flowTask.setTaskId ( task.getId () );
			flowTask.setTaskDefKey ( task.getTaskDefinitionKey () );
			flowTask.setCreateTime ( task.getCreateTime () );
			flowTask.setProcDefId ( task.getProcessDefinitionId () );
			flowTask.setExecutionId ( task.getExecutionId () );
			flowTask.setTaskName ( task.getName () );
			// 流程定义信息
			ProcessDefinition pd = repositoryService.createProcessDefinitionQuery ().processDefinitionId ( task.getProcessDefinitionId () ).singleResult ();
			flowTask.setDeployId ( pd.getDeploymentId () );
			flowTask.setProcDefName ( pd.getName () );
			flowTask.setProcDefVersion ( pd.getVersion () );
			flowTask.setProcInsId ( task.getProcessInstanceId () );

			// 流程发起人信息
			HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery ().processInstanceId ( task.getProcessInstanceId () ).singleResult ();
			//			SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
			//			flowTask.setStartUserId(startUser.getUserId().toString());
			//			flowTask.setStartUserName(startUser.getNickName());
			//			flowTask.setStartDeptName(Objects.nonNull(startUser.getDept()) ? startUser.getDept().getDeptName() : "");
			taskDtoList.add ( flowTask );
		}
		return Result.success ( taskDtoList );
	}

	@Operation ( summary = "审批任务", description = "审批任务" )
	@PostMapping ( value = "/complete" )
	public Result < String > complete ( @RequestBody TaskVo taskVo ) {
		Task task = taskService.createTaskQuery ().taskId ( taskVo.getTaskId () ).singleResult ();
		Map<String,Object> variables = taskVo.getProcessVariables ();
		if ( Objects.isNull ( task ) ) {
			return Result.error ( "任务不存在" );
		}
		if ( DelegationState.PENDING.equals ( task.getDelegationState () ) ) {
			taskService.addComment ( taskVo.getTaskId () , taskVo.getProcessInstanceId () ,
					FlowComment.DELEGATE.getType () , taskVo.getRemark () );
			taskService.resolveTask ( taskVo.getTaskId () , taskVo.getProcessVariables () );
		}
		else {
			taskService.addComment ( taskVo.getTaskId () , taskVo.getProcessInstanceId () ,
					FlowComment.NORMAL.getType () , taskVo.getRemark () );
			taskService.setAssignee ( taskVo.getTaskId () , taskVo.getUserId () );
			taskService.complete ( taskVo.getTaskId () , variables );
		}
		return Result.success ();
	}

	@PostMapping ( "finishedList" )
	@Operation ( summary = "我的已办任务", description = "我的已办任务" )
	public Result < List<FlowTaskDto> > finishedList ( @RequestBody TaskVo dto ) {
		List< HistoricTaskInstance > historicTaskInstanceList  = historyService.createHistoricTaskInstanceQuery()
				.includeProcessVariables()
				.finished()
				.taskAssignee(dto.getUserId ())
				.orderByHistoricTaskInstanceEndTime()
				.desc().list ();
		List<FlowTaskDto> hisTaskList = new ArrayList<>();
		for (HistoricTaskInstance histTask : historicTaskInstanceList) {
			FlowTaskDto flowTask = new FlowTaskDto();
			// 当前流程信息
			flowTask.setTaskId(histTask.getId());
			// 审批人员信息
			flowTask.setCreateTime(histTask.getCreateTime());
			flowTask.setFinishTime(histTask.getEndTime());
			flowTask.setDuration(getDate(histTask.getDurationInMillis()));
			flowTask.setProcDefId(histTask.getProcessDefinitionId());
			flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
			flowTask.setTaskName(histTask.getName());

			// 流程定义信息
			ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
					.processDefinitionId(histTask.getProcessDefinitionId())
					.singleResult();
			flowTask.setDeployId(pd.getDeploymentId());
			flowTask.setProcDefName(pd.getName());
			flowTask.setProcDefVersion(pd.getVersion());
			flowTask.setProcInsId(histTask.getProcessInstanceId());
			flowTask.setHisProcInsId(histTask.getProcessInstanceId());

			// 流程发起人信息
			HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
					.processInstanceId(histTask.getProcessInstanceId())
					.singleResult();
			hisTaskList.add(flowTask);
		}

		return Result.success ( hisTaskList );
	}

	@Operation ( summary = "根据流程实例id获取审批详情", description = "根据流程实例id获取审批详情" )
	@PostMapping ( value = "/getProcessDetail" )
	public Result < List < ProcessDetail > > getProcessDetail ( @RequestBody TaskVo taskVo ) {
		List < HistoricTaskInstance > taskInstances = historyService.createHistoricTaskInstanceQuery ()
				.processInstanceId ( taskVo.getProcessInstanceId () )
				.orderByHistoricTaskInstanceStartTime ().asc ().list ();

		List< Comment > commentList = taskService.getProcessInstanceComments ( taskVo.getProcessInstanceId() );
		List < ProcessDetail > processDetails = new ArrayList <> ();
		for ( HistoricTaskInstance hti : taskInstances ) {

			ProcessDetail processDetail = new ProcessDetail ();
			processDetail.setProName ( hti.getName () );
			processDetail.setUserId ( hti.getAssignee () );
			processDetail.setStartTime ( hti.getCreateTime () );
			processDetail.setEndTime ( hti.getEndTime () );
			commentList.forEach ( comment -> {
				if ( hti.getId ().equals ( comment.getTaskId () ) ) {
					processDetail.setRemark ( comment.getFullMessage () );
				}
			} );
			processDetails.add ( processDetail );
		}
		return Result.success ( processDetails );
	}

	private String getDate ( long ms ) {

		long day = ms / ( 24 * 60 * 60 * 1000 );
		long hour = ( ms / ( 60 * 60 * 1000 ) - day * 24 );
		long minute = ( ( ms / ( 60 * 1000 ) ) - day * 24 * 60 - hour * 60 );
		long second = ( ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60 );

		if ( day > 0 ) {
			return day + "天" + hour + "小时" + minute + "分钟";
		}
		if ( hour > 0 ) {
			return hour + "小时" + minute + "分钟";
		}
		if ( minute > 0 ) {
			return minute + "分钟";
		}
		if ( second > 0 ) {
			return second + "秒";
		}
		else {
			return 0 + "秒";
		}
	}
}
